﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Drawing;
using System.Windows.Forms;
using Terminal.Advanced_AEUC_settings_controls.Advanced_controls;
using Auxiliaries;
using System.IO;

namespace OMXTreeViewNodes
{
    public interface IOMXTreeViewParentForm
    {
        void OMXParamTreeViewNodeSelected(TreeNode Node);
        void saveOMXParamTreeView(OMXParamTreeViewSectionNode sect, BinaryWriter fBin);
        void saveOMXParamTreeView(OMXParamTreeViewRootNode root, FileInfo fInf);
    }

    #region OMX Param tree view root node
    /// <summary>
    /// An OMX component - the root node of the tree view representing an OMX component
    /// </summary>
    public class OMXParamTreeViewRootNode : TreeNode
    {
        const string CTX_MENU_SAVE = "Save Parameter structure definition tree";
        const string CTX_MENU_UNLOAD = "Unload Parameter structure definition tree";

        const string CTX_MENU_RENAME = "Rename root";
        const string CTX_MENU_ADD_SUB = "Add Parameter sub-level";
        const string CTX_MENU_SUB_SEC_ORDER = "Order available subsections";

        const string CTX_MENU_OMX_RENAME = "Rename OMX component name";
        const string CTX_MENU_COMP_MESSAGING = "Component related messaging";
        const string CTX_MENU_REQLOAD_DCC = "Request and load DCC files";
        const string CTX_MENU_SET_DCC_CFG = "Set DCC config file";
        const string CTX_MENU_SET_DCC_URI = "Set DCC URI request id";
        const string CTX_MENU_SET_DCC_BUF = "Set DCC Buffer pointer id";

        const string CTX_MENU_COMP_GET_INST_HANDLE = "get";
        const string CTX_MENU_COMP_SET_INST_HANDLE = "set";

        const string CTX_MENU_COMP_GET_PORTS = "get information";
        const string CTX_MENU_COMP_ALLOC_PORT_BUFFS = "allocate buffers";
        const string CTX_MENU_COMP_LINK_PORTS = "link ports";

        //const string CTX_MENU_COMP_CMDS_IDLE = "set state idle";
        //const string CTX_MENU_COMP_CMDS_EXEC = "set state executing";

        const string CTX_MENU_COMP_MARSHALLING_ALLOC = "allocate";
        const string CTX_MENU_COMP_MARSHALLING_LAOD = "load file";
        const string CTX_MENU_COMP_MARSHALLING_FREE = "free";
        const string CTX_MENU_COMP_MARSHALLING_DUMP = "dump to file";

        const string CTX_MENU_COMP_CONFIG_MULTPL = "Send multiple params/configurations";
        const string CTX_MENU_COMP_STRUCT_MARSHALLING = "Structure marshalling";
        /// <summary>
        /// Public constructor
        /// </summary>
        /// <param name="iName">Display name</param>
        /// <param name="iPar">Parent OMX Param form</param>
        /// <param name="fileSaveName">File for serialization</param>
        public OMXParamTreeViewRootNode(string iName, IOMXTreeViewParentForm iPar, string fileSaveName)
            : base(iName)
        {
            ParentForm = iPar;
            refUCTabPageControl = new UCTabPage();

            prepareContextMenu();

            infUCTabPageControlsFile = new FileInfo(fileSaveName);

            timeoutTrigger = new System.Windows.Forms.Timer();
            timeoutTrigger.Enabled = true;
            //Is this a viable unique identifier for the created instance?
            guid = DateTime.Now.Ticks;

            refUCTabPageControl.OnCompInstUpdate += new UCTabPage.omxCompUpdate(refUCTabPageControl_OnCompInstUpdateReport);
        }

        void prepareContextMenu()
        {
            ContextMenu = new ContextMenu();
            ContextMenu.Popup += new EventHandler(omMarshalling_Popup);
            EventHandler eh = new EventHandler(ContextMenuHandler);

            MenuItem omIt = new MenuItem("Component->");
            MenuItem omInst = new MenuItem("handle");
            omInst.MenuItems.Add(CTX_MENU_COMP_GET_INST_HANDLE, eh);
            omInst.MenuItems.Add(CTX_MENU_COMP_SET_INST_HANDLE, eh);
            omIt.MenuItems.Add(omInst);

            MenuItem omPort = new MenuItem("ports");
            omPort.MenuItems.Add(CTX_MENU_COMP_GET_PORTS, eh);
            omPort.MenuItems.Add(CTX_MENU_COMP_ALLOC_PORT_BUFFS, eh);
            omPort.MenuItems.Add(CTX_MENU_COMP_LINK_PORTS, eh);
            omIt.MenuItems.Add(omPort);

            //MenuItem omCmds = new MenuItem("commands");
            //omCmds.MenuItems.Add(CTX_MENU_COMP_CMDS_IDLE, eh);
            //omCmds.MenuItems.Add(CTX_MENU_COMP_CMDS_EXEC, eh);
            //omIt.MenuItems.Add(omCmds);

            MenuItem omMarshalling = new MenuItem("memory allocations");
            MenuItem addPtr = new MenuItem("NULL");
            addPtr.MenuItems.Add(CTX_MENU_COMP_MARSHALLING_ALLOC, eh);
            omMarshalling.MenuItems.Add(addPtr);
            omIt.MenuItems.Add(omMarshalling);

            ContextMenu.MenuItems.Add(omIt);

            MenuItem prIt = new MenuItem("Properties");
            prIt.MenuItems.Add(CTX_MENU_REQLOAD_DCC, eh);
            prIt.MenuItems.Add(CTX_MENU_OMX_RENAME, eh);
            prIt.MenuItems.Add(CTX_MENU_COMP_MESSAGING, eh);
            prIt.MenuItems.Add(CTX_MENU_SET_DCC_CFG, eh);
            prIt.MenuItems.Add(CTX_MENU_SET_DCC_URI, eh);
            prIt.MenuItems.Add(CTX_MENU_SET_DCC_BUF, eh);
            ContextMenu.MenuItems.Add(prIt);

            MenuItem edIt = new MenuItem("Edit");
            edIt.MenuItems.Add(CTX_MENU_RENAME, eh);
            edIt.MenuItems.Add(CTX_MENU_ADD_SUB, eh);
            edIt.MenuItems.Add(CTX_MENU_SUB_SEC_ORDER, eh);
            ContextMenu.MenuItems.Add(edIt);

            ContextMenu.MenuItems.Add(CTX_MENU_COMP_CONFIG_MULTPL, eh);
            ContextMenu.MenuItems.Add(CTX_MENU_COMP_STRUCT_MARSHALLING, eh);
            ContextMenu.MenuItems.Add(CTX_MENU_SAVE, eh);
            ContextMenu.MenuItems.Add(CTX_MENU_UNLOAD, eh);
        }

        void omMarshalling_Popup(object sender, EventArgs e)
        {
            MenuItem omMarshalling = (MenuItem)(((ContextMenu)sender).MenuItems[0].MenuItems[2]);
            EventHandler eh = new EventHandler(MarshallingMenuHandler);

            omMarshalling.MenuItems.Clear();

            MenuItem addPtr = new MenuItem("NULL");
            addPtr.MenuItems.Add(CTX_MENU_COMP_MARSHALLING_ALLOC, eh);
            addPtr.MenuItems.Add(CTX_MENU_COMP_MARSHALLING_LAOD, eh);
            omMarshalling.MenuItems.Add(addPtr);

            for (int i = 0; i < compMemAllocs.Count; i++)
            {
                addPtr = new MenuItem(HEX_converter.ToHexString(compMemAllocs[i].address));
                addPtr.MenuItems.Add(CTX_MENU_COMP_MARSHALLING_LAOD, eh);
                addPtr.MenuItems.Add(CTX_MENU_COMP_MARSHALLING_FREE, eh);
                addPtr.MenuItems.Add(CTX_MENU_COMP_MARSHALLING_DUMP, eh);
                omMarshalling.MenuItems.Add(addPtr);
            }
        }

        /// <summary>
        /// The OMX Component version number
        /// </summary>
        public const int OMXCompRootNodeVerMin = 0;
        /// <summary>
        /// The OMX Component version number
        /// </summary>
        public const int OMXCompRootNodeVerMax = 3;
        /// <summary>
        /// Internal OMX component root version
        /// </summary>
        public int OMXCompRootNodeVer = 3;
        Int64 guid;
        IOMXTreeViewParentForm ParentForm;
        UCTabPage refUCTabPageControl;
        /// <summary>
        /// Returns reference to the loaded user interface control
        /// </summary>
        public UCTabPage UCTabPage
        {
            get
            {
                return refUCTabPageControl;
            }
        }
        bool SuccessfulLoad = false;
        /// <summary>
        /// Loads user control definitions file, loads it to the specified parent control and returns reference to it.
        /// </summary>
        /// <param name="parent">Parent control that will hold the loaded user controls definitions</param>
        /// <returns>Reference user control definitions</returns>
        public UCTabPage loadUCTabPage(Control parent)
        {
            parent.Controls.Add(refUCTabPageControl);
            refUCTabPageControl.Anchor = AnchorStyles.Top | AnchorStyles.Bottom | AnchorStyles.Left | AnchorStyles.Right;
            refUCTabPageControl.Location = new Point(0, 0);
            refUCTabPageControl.Size = parent.Size;
            if (!SuccessfulLoad)
            {
                if (infUCTabPageControlsFile != null)
                {
                    infUCTabPageControlsFile.Refresh();
                    if (infUCTabPageControlsFile.Exists)
                    {
                        refUCTabPageControl.LoadUserSettingDefinitionsFile(infUCTabPageControlsFile);
                        SuccessfulLoad = true;
                    }
                    else
                        return null;
                }
                else
                    return null;

                UpdateOMXCompInstanceId();
            }

            return refUCTabPageControl;
        }

        /// <summary>
        /// User defined controls and structures serialization file
        /// </summary>
        public FileInfo infUCTabPageControlsFile;
        /// <summary>
        /// OMX Component tree view serialization file
        /// </summary>
        public FileInfo infParamTreeViewFile = null;
        uint compInstanceID = 0;
        System.Windows.Forms.Timer timeoutTrigger;
        /// <summary>
        /// OMX Component name (as should be found in the IL system)
        /// </summary>
        public string OMXCopmName = "OMX.NONAME";
        /// <summary>
        /// File containing configuration for DCC related data
        /// </summary>
        public string cfgDCC = "";
        /// <summary>
        /// DCC URI request id
        /// </summary>
        public string uriDCC = "";
        /// <summary>
        /// DCC Buffer pointer parameter id
        /// </summary>
        public string bufDCC = "";
        /// <summary>
        /// Get/Set method for the component instance handle
        /// </summary>
        public uint CompInstanceID
        {
            get
            {
                return compInstanceID;
            }
            set
            {
                compInstanceID = value;
                UpdateOMXCompInstanceId();
            }
        }

        /// <summary>
        /// Data structure for target allocated memory
        /// </summary>
        public class MemMarshalling
        {
            /// <summary>
            /// Address pointer
            /// </summary>
            public UInt32 address;
            /// <summary>
            /// Allocation size
            /// </summary>
            public UInt32 size;

            /// <summary>
            /// Constructor
            /// </summary>
            public MemMarshalling()
            {
                address = 0;
                size = 0;
            }
            /// <summary>
            /// Constructor
            /// </summary>
            /// <param name="iAddr">Address pointer</param>
            /// <param name="iSz">Allocation size</param>
            public MemMarshalling(UInt32 iAddr, UInt32 iSz)
            {
                address = iAddr;
                size = iSz;
            }
            /// <summary>
            /// Overrided ToString method
            /// </summary>
            /// <returns>Address and size</returns>
            public override string ToString()
            {
                return size.ToString() + " bytes at " + HEX_converter.ToHexString(address);
            }
        }
        /// <summary>
        /// List of all of the marshalled memory allocations associated with this component
        /// </summary>
        public List<MemMarshalling> compMemAllocs = new List<MemMarshalling>();

        Terminal.Advanced_AEUC_settings_controls.Advanced_controls.UCTabPage.DCCURIConllected evnHdlDccUri = null;

        private void ContextMenuHandler(object sender, EventArgs ea)
        {
            MenuItem tmpItem = (MenuItem)sender;

            if (tmpItem.Text == CTX_MENU_ADD_SUB)
            {
                AuxQueryBox subCrtForm = new AuxQueryBox(AuxQueryBox.IfModeSel.Section_create);
                if (subCrtForm.ShowDialog() == DialogResult.OK)
                {
                    TreeNode tmpNode = new OMXParamTreeViewSectionNode(subCrtForm.GetInputText(), null, null, refUCTabPageControl, ParentForm);
                    Nodes.Add(tmpNode);
                    TreeView.SelectedNode = tmpNode;
                    ParentForm.OMXParamTreeViewNodeSelected(tmpNode);
                }
            }
            else if (tmpItem.Text == CTX_MENU_UNLOAD)
            {
                TreeView tmpParentViewRef = TreeView;
                TreeView.Nodes.Remove(this);
                ParentForm.OMXParamTreeViewNodeSelected(null);
                if (tmpParentViewRef.Nodes.Count > 0)
                {
                    tmpParentViewRef.SelectedNode = tmpParentViewRef.Nodes[0];
                    ParentForm.OMXParamTreeViewNodeSelected(tmpParentViewRef.SelectedNode);
                }
            }
            else if (tmpItem.Text == CTX_MENU_SAVE)
            {
                ParentForm.saveOMXParamTreeView(this, infParamTreeViewFile);
            }
            else if (tmpItem.Text == CTX_MENU_RENAME)
            {
                AuxQueryBox subCrtForm = new AuxQueryBox(AuxQueryBox.IfModeSel.Section_create, Text);
                if (subCrtForm.ShowDialog() == DialogResult.OK)
                {
                    Text = subCrtForm.GetInputText();
                }
            }
            else if (tmpItem.Text == CTX_MENU_SET_DCC_CFG)
            {
                OpenFileDialog ofd = new OpenFileDialog();
                ofd.DefaultExt = "dcc";
                ofd.Filter = "*.dcc|*.dcc";
                if (ofd.ShowDialog() == DialogResult.OK)
                {
                    FileInfo finf = new FileInfo(ofd.FileName);
                    if (finf.Exists && finf.Extension == ".dcc")
                    {
                        cfgDCC = finf.FullName;
                    }
                    else
                    {
                        MessageBox.Show("Invalid file selected: " + finf.FullName);
                    }
                }
            }
            else if (tmpItem.Text == CTX_MENU_SET_DCC_URI)
            {
                AuxQueryBox subCrtForm = new AuxQueryBox(AuxQueryBox.IfModeSel.Section_create, Text);
                if (subCrtForm.ShowDialog() == DialogResult.OK)
                {
                    uriDCC = subCrtForm.GetInputText();
                }
            }
            else if (tmpItem.Text == CTX_MENU_SET_DCC_BUF)
            {
                AuxQueryBox subCrtForm = new AuxQueryBox(AuxQueryBox.IfModeSel.Section_create, Text);
                if (subCrtForm.ShowDialog() == DialogResult.OK)
                {
                    bufDCC = subCrtForm.GetInputText();
                }
            }
            else if (tmpItem.Text == CTX_MENU_REQLOAD_DCC)
            {
                if (evnHdlDccUri == null)
                    evnHdlDccUri = new Terminal.Advanced_AEUC_settings_controls.Advanced_controls.UCTabPage.DCCURIConllected(refUCTabPageControl_OnDCCURICollected);
                refUCTabPageControl.OnDCCURICollected += evnHdlDccUri;
                refUCTabPageControl.marshallDCCCollectURIInfos(CompInstanceID, uriDCC);
            }
            else if (tmpItem.Text == CTX_MENU_COMP_SET_INST_HANDLE)
            {
                AuxQueryBox subCrtForm = new AuxQueryBox(AuxQueryBox.IfModeSel.Component_instance);
                if (subCrtForm.ShowDialog() == DialogResult.OK)
                {
                    uint id;
                    string str_id = subCrtForm.GetInputText();
                    if (!uint.TryParse(str_id, out id))
                    {
                        CompInstanceID = unchecked((uint)-1);
                    }
                    else
                    {
                        CompInstanceID = id;
                    }
                }
            }
            else if (tmpItem.Text == CTX_MENU_COMP_GET_INST_HANDLE)
            {
                timeoutTrigger.Interval = 5000;
                //timeoutTrigger.Tick += new EventHandler(timeoutTrigger_Tick_GetCompHandle);
                //timeoutTrigger.Start();
                //refUCTabPageControl.OnCompInstUpdate += new UCTabPage.omxCompUpdate(refUCTabPageControl_OnCompInstUpdateReport);
                refUCTabPageControl.GetComponentInstanceHandle(OMXCopmName);
            }
            else if (tmpItem.Text == CTX_MENU_OMX_RENAME)
            {
                AuxQueryBox subCrtForm = new AuxQueryBox(AuxQueryBox.IfModeSel.Section_create, OMXCopmName);
                if (subCrtForm.ShowDialog() == DialogResult.OK)
                {
                    OMXCopmName = subCrtForm.GetInputText();
                }
            }
            else if (tmpItem.Text == CTX_MENU_COMP_CONFIG_MULTPL)
            {
                OMXParamTreeViewSectionNode[] secArray = new OMXParamTreeViewSectionNode[Nodes.Count];
                Nodes.CopyTo(secArray, 0);
                ParamConfigSubSectionOps pcssOrder = new ParamConfigSubSectionOps(secArray, ParamConfigSubSectionOps.OperationModes.SectionSelection);
                if (pcssOrder.ShowDialog() == DialogResult.OK)
                {
                    List<int> selIndeces = new List<int>();
                    OMXParamTreeViewSectionNode[] secNodes = pcssOrder.GetSelectedNodeArray();
                    for (int i = 0; i < secNodes.Length; i++)
                    {
                        selIndeces.AddRange(secNodes[i].GetOMXParamTabPageRefIndces());
                    }
                    refUCTabPageControl.multiParamStructureSettingsTransfer(selIndeces.ToArray());
                }
            }
            else if (tmpItem.Text == CTX_MENU_SUB_SEC_ORDER)
            {
                OMXParamTreeViewSectionNode[] secArray = new OMXParamTreeViewSectionNode[Nodes.Count];
                Nodes.CopyTo(secArray, 0);
                ParamConfigSubSectionOps pcssOrder = new ParamConfigSubSectionOps(secArray, ParamConfigSubSectionOps.OperationModes.SectionReordering);
                if (pcssOrder.ShowDialog() == DialogResult.OK)
                {
                    Nodes.Clear();
                    Nodes.AddRange(pcssOrder.GetSelectedNodeArray());
                }
            }
            else if (tmpItem.Text == CTX_MENU_COMP_GET_PORTS)
            {
                timeoutTrigger.Interval = 5000;
                //timeoutTrigger.Tick += new EventHandler(timeoutTrigger_Tick_GetCompHandle);
                //timeoutTrigger.Start();
                //refUCTabPageControl.OnCompInstUpdate += new UCTabPage.omxCompUpdate(refUCTabPageControl_OnCompInstUpdateReport);
                refUCTabPageControl.GetComponentInstancePorts(CompInstanceID);
            }
            else if (tmpItem.Text == CTX_MENU_COMP_ALLOC_PORT_BUFFS)
            {
                AuxQueryBox subCrtForm = new AuxQueryBox(AuxQueryBox.IfModeSel.Comp_port_number);
                if (subCrtForm.ShowDialog() == DialogResult.OK)
                {
                    string portsStr = subCrtForm.GetInputText();

                    List<uint> portsNum = integerInputParser(portsStr);

                    if (portsNum != null)
                    {
                        timeoutTrigger.Interval = 5000;
                        //timeoutTrigger.Tick += new EventHandler(timeoutTrigger_Tick_GetCompHandle);
                        //timeoutTrigger.Start();
                        compResponsesWaitCount = portsNum.Count;
                        //refUCTabPageControl.OnCompInstUpdate += new UCTabPage.omxCompUpdate(refUCTabPageControl_OnCompInstUpdateReport);
                        for (int i = 0; i < portsNum.Count; i++)
                        {
                            refUCTabPageControl.AllocComponentPortBuffs(CompInstanceID, portsNum[i]);
                        }
                    }
                }
            }
            else if (tmpItem.Text == CTX_MENU_COMP_LINK_PORTS)
            {
                AuxQueryBox subCrtForm = new AuxQueryBox(AuxQueryBox.IfModeSel.Comp_port_number);
                if (subCrtForm.ShowDialog() == DialogResult.OK)
                {
                    string portsStr = subCrtForm.GetInputText();

                    List<uint> portsNum = integerInputParser(portsStr);

                    if (portsNum != null)
                    {
                        timeoutTrigger.Interval = 5000;
                        //timeoutTrigger.Tick += new EventHandler(timeoutTrigger_Tick_GetCompHandle);
                        //timeoutTrigger.Start();
                        //refUCTabPageControl.OnCompInstUpdate += new UCTabPage.omxCompUpdate(refUCTabPageControl_OnCompInstUpdateReport);
                        refUCTabPageControl.LinkComponentPorts(CompInstanceID, portsNum[0], portsNum[1], portsNum[2]);
                    }
                }
            }
            else if (tmpItem.Text == CTX_MENU_COMP_MESSAGING)
            {
                refUCTabPageControl.GetOMXComponentMessaging();
            }
            else if (tmpItem.Text == CTX_MENU_COMP_STRUCT_MARSHALLING)
            {
                OMXParamTreeViewSectionNode[] secArray = new OMXParamTreeViewSectionNode[Nodes.Count];
                Nodes.CopyTo(secArray, 0);
                ParamConfigSubSectionOps pcssOrder = new ParamConfigSubSectionOps(secArray, ParamConfigSubSectionOps.OperationModes.SectionSelection);
                if (pcssOrder.ShowDialog() == DialogResult.OK)
                {
                    List<int> selIndeces = new List<int>();
                    OMXParamTreeViewSectionNode[] secNodes = pcssOrder.GetSelectedNodeArray();
                    for (int i = 0; i < secNodes.Length; i++)
                    {
                        selIndeces.AddRange(secNodes[i].GetOMXParamTabPageRefIndces());
                    }
                    refUCTabPageControl.multiParamStructureSerialization(selIndeces.ToArray());
                }
            }
            /*
            else if (tmpItem.Text == CTX_MENU_COMP_CMDS_IDLE)
            {
                timeoutTrigger.Interval = 5000;
                //timeoutTrigger.Tick += new EventHandler(timeoutTrigger_Tick_GetCompHandle);
                //timeoutTrigger.Start();
                refUCTabPageControl.OnCompInstUpdate += new UCTabPage.omxCompUpdate(refUCTabPageControl_OnCompInstUpdateReport);
                refUCTabPageControl.SendCompCommand(CompInstanceID, 0, 2, 0);
            }
            else if (tmpItem.Text == CTX_MENU_COMP_CMDS_EXEC)
            {
                timeoutTrigger.Interval = 5000;
                //timeoutTrigger.Tick += new EventHandler(timeoutTrigger_Tick_GetCompHandle);
                //timeoutTrigger.Start();
                refUCTabPageControl.OnCompInstUpdate += new UCTabPage.omxCompUpdate(refUCTabPageControl_OnCompInstUpdateReport);
                refUCTabPageControl.SendCompCommand(CompInstanceID, 0, 3, 0);
            }
            */
        }

        void refUCTabPageControl_OnDCCURICollected(string[] sensors)
        {
            refUCTabPageControl.OnDCCURICollected -= evnHdlDccUri;
            evnHdlDccUri = null;
            refUCTabPageControl.marshallDCC(CompInstanceID, new FileInfo(cfgDCC), sensors, bufDCC);
        }

        private void MarshallingMenuHandler(object sender, EventArgs ea)
        {
            MenuItem tmpItem = (MenuItem)sender;

            if (tmpItem.Text == CTX_MENU_COMP_MARSHALLING_ALLOC)
            {
                int memSz;
                AuxQueryBox subCrtForm = new AuxQueryBox(AuxQueryBox.IfModeSel.Comp_port_number, "NULL");
                if (subCrtForm.ShowDialog() == DialogResult.OK)
                {
                    if (int.TryParse(subCrtForm.GetInputText(), out memSz))
                    {
                        refUCTabPageControl.marshallingMemAlloc(CompInstanceID, memSz);
                    }
                    else
                    {
                        MessageBox.Show("Please type in valid memy size value");
                    }
                }
            }
            else if (tmpItem.Text == CTX_MENU_COMP_MARSHALLING_LAOD)
            {
                OpenFileDialog ofd = new OpenFileDialog();
                if (ofd.ShowDialog() == DialogResult.OK)
                {
                    if (((MenuItem)tmpItem.Parent).Text == "NULL")
                    {
                        refUCTabPageControl.marshallingMemAllocFileLoad(CompInstanceID, new FileInfo(ofd.FileName));
                    }
                    else
                    {
                        UInt64 memPtr;
                        if (HEX_converter.ToBinary(((MenuItem)tmpItem.Parent).Text, out memPtr))
                        {
                            for (int i = 0; i < compMemAllocs.Count; i++)
                            {
                                if (memPtr == compMemAllocs[i].address)
                                {
                                    refUCTabPageControl.marshallingMemFileLoad(CompInstanceID, new FileInfo(ofd.FileName), (int)memPtr);
                                }
                            }
                            return;
                        }
                        MessageBox.Show("Error reading the pointer value!");
                    }
                }
            }
            else if (tmpItem.Text == CTX_MENU_COMP_MARSHALLING_FREE)
            {
                UInt64 memPtr;
                if (HEX_converter.ToBinary(((MenuItem)tmpItem.Parent).Text, out memPtr))
                {
                    for (int i = 0; i < compMemAllocs.Count; i++)
                    {
                        if (memPtr == compMemAllocs[i].address)
                        {
                            refUCTabPageControl.marshallingMemFree(CompInstanceID, (int)memPtr);
                            compMemAllocs.RemoveAt(i);
                            return;
                        }
                    }
                }

                MessageBox.Show("Error reading the pointer value!");
            }
            else if (tmpItem.Text == CTX_MENU_COMP_MARSHALLING_DUMP)
            {
                int memSz;
                AuxQueryBox subCrtForm = new AuxQueryBox(AuxQueryBox.IfModeSel.Comp_port_number, "NULL");
                if (subCrtForm.ShowDialog() == DialogResult.OK)
                {
                    if (int.TryParse(subCrtForm.GetInputText(), out memSz))
                    {
                        UInt64 memPtr;
                        if (HEX_converter.ToBinary(((MenuItem)tmpItem.Parent).Text, out memPtr))
                        {
                            for (int i = 0; i < compMemAllocs.Count; i++)
                            {
                                if (memPtr == compMemAllocs[i].address)
                                {
                                    refUCTabPageControl.marshallingMemDump(CompInstanceID, (int)memPtr, memSz);
                                    return;
                                }
                            }
                        }

                        MessageBox.Show("Error reading the pointer value!");
                    }
                    else
                    {
                        MessageBox.Show("Please type in valid memy size value");
                    }
                }
            }
        }

        List<uint> integerInputParser(string portsStr)
        {
            uint portNum;
            string tmpPortNum = "";
            List<uint> portsNum = new List<uint>();

            for (int i = 0; i <= portsStr.Length; i++)
            {
                if (i < portsStr.Length && portsStr[i] >= '0' && portsStr[i] <= '9')
                {
                    tmpPortNum += portsStr[i];
                }
                else if ((i < portsStr.Length && portsStr[i] == ',') || (i == portsStr.Length && tmpPortNum != ""))
                {
                    if (!uint.TryParse(tmpPortNum, out portNum))
                    {
                        MessageBox.Show("Please input valid port(s) number!");
                        return null;
                    }
                    else
                    {
                        tmpPortNum = "";
                        portsNum.Add(portNum);
                    }
                }
                else if (i < portsStr.Length && (portsStr[i] != ' ' && portsStr[i] != '\t'))
                {
                    MessageBox.Show("Invalid input format!\nPlease use the following format: port_number, port_number, port_number, ...");
                    return null;
                }
            }

            return portsNum;
        }

        int compResponsesWaitCount = 0;

        void timeoutTrigger_Tick_WaitCompUpdate(object sender, EventArgs e)
        {
            timeoutTrigger.Stop();
            compResponsesWaitCount = 0;
            //refUCTabPageControl.OnCompInstUpdate -= new UCTabPage.omxCompUpdate(refUCTabPageControl_OnCompInstUpdateReport);
            refUCTabPageControl.GetCommObject().errorMessage("Wait for component response timed out.");
        }

        void refUCTabPageControl_OnCompInstUpdateReport(UCTabPage.ParameterStreamParseResult updateEvent, object evData)
        {
            switch (updateEvent)
            {
                case UCTabPage.ParameterStreamParseResult.OMX_COMP_HANDLE:
                    //refUCTabPageControl.OnCompInstUpdate -= new UCTabPage.omxCompUpdate(refUCTabPageControl_OnCompInstUpdateReport);
                    if (((UCTabPage.CompInstInfo)evData).name == OMXCopmName)
                    {
                        CompInstanceID = (uint)((UCTabPage.CompInstInfo)evData).id;
                        refUCTabPageControl.GetCommObject().errorMessage("Component id received: " + CompInstanceID);
                    }
                    break;
                case UCTabPage.ParameterStreamParseResult.OMX_COMP_PORTS_INFO:
                    UCTabPage.CompPortInfo ports = (UCTabPage.CompPortInfo)evData;
                    if (ports.compId == CompInstanceID)
                    {
                        //refUCTabPageControl.OnCompInstUpdate -= new UCTabPage.omxCompUpdate(refUCTabPageControl_OnCompInstUpdateReport);
                        refUCTabPageControl.GetCommObject().errorMessage("Ports discovered: " + ports.ports.Length.ToString());
                        for (int i = 0; i < ports.ports.Length; i++)
                        {
                            refUCTabPageControl.GetCommObject().errorMessage("Port number: " + ports.ports[i].portNum.ToString());
                            refUCTabPageControl.GetCommObject().errorMessage("Port direction: " + ports.ports[i].portDir.ToString());
                            refUCTabPageControl.GetCommObject().errorMessage("Port domain: " + ports.ports[i].portDom.ToString());
                            refUCTabPageControl.GetCommObject().errorMessage("...");
                        }
                    }
                    break;
                case UCTabPage.ParameterStreamParseResult.SYS_MARSHAL_ALLOC:
                    Terminal.Advanced_AEUC_settings_controls.Settings_AUX.GenMSG tst = (Terminal.Advanced_AEUC_settings_controls.Settings_AUX.GenMSG)evData;
                    int compId = (int)((UInt32)tst.payloadStruct[0]);//Access first item in bytestream that should be the component instance id.
                    uint mhsSize = (uint)((UInt32)tst.payloadStruct[1]);//Access second item in bytestream that should be the allocation size.
                    uint mhsPtr = (uint)((UInt32)tst.payloadStruct[2]);//Access third item in bytestream that should be the allocated pointer.

                    if (compId == CompInstanceID)
                    {
                        compMemAllocs.Add(new MemMarshalling(mhsPtr, mhsSize));
                    }
                    break;
                /*
                case UCTabPage.ParameterStreamParseResult.OMX_COMP_CMD:
                    //refUCTabPageControl.OnCompInstUpdate -= new UCTabPage.omxCompUpdate(refUCTabPageControl_OnCompInstUpdateReport);
                    refUCTabPageControl.GetCommObject().errorMessage("Component command \"" + ((uint)((int)evData)).ToString() + "\" acknowledge received.");
                    break;
                case UCTabPage.ParameterStreamParseResult.OMX_COMP_PORT_BUFF_ALLOC:
                    //if (--compResponsesWaitCount == 0)
                        //refUCTabPageControl.OnCompInstUpdate -= new UCTabPage.omxCompUpdate(refUCTabPageControl_OnCompInstUpdateReport);
                    refUCTabPageControl.GetCommObject().errorMessage("Component port buffers allocated.");
                    break;
                */
                default:
                    break;
            }
        }
        /// <summary>
        /// Loads the sser defined controls and structures
        /// </summary>
        public void LoadUCTabPageControlsFile()
        {
            if (Nodes.Count > 0)
                refUCTabPageControl.LoadUserSettingDefinitionsFile(infUCTabPageControlsFile);
        }
        /// <summary>
        /// Updates a structure tab page index (instance mathcing of tab pages with tree view)
        /// </summary>
        /// <param name="idx"></param>
        public void UpdateOMXParamTabPageRefIndx(int idx)
        {
            for (int i = 0; i < Nodes.Count; i++)
            {
                ((OMXParamTreeViewSectionNode)Nodes[i]).UpdateOMXParamTabPageRefIndx(idx);
            }
            ParentForm.saveOMXParamTreeView(this, infParamTreeViewFile);
        }
        /// <summary>
        /// Updates the OMX component instance handle throughout the present structure definitions and subsections
        /// </summary>
        public void UpdateOMXCompInstanceId()
        {
            for (int i = 0; i < Nodes.Count; i++)
            {
                ((OMXParamTreeViewSectionNode)Nodes[i]).UpdateOMXCompInstanceId(compInstanceID);
            }
        }

        /// <summary>
        /// Returns the current advanced user control definition file name
        /// </summary>
        /// <returns>Full file name</returns>
        public string uctabDefFilePath()
        {
            if (infUCTabPageControlsFile != null && infUCTabPageControlsFile.Exists)
            {
                return infUCTabPageControlsFile.FullName;
            }
            return "no file";
        }
    }
    #endregion
    #region OMX Param tree view section node
    /// <summary>
    /// An OMX component - a subsection node of the tree view representing an OMX component
    /// </summary>
    public class OMXParamTreeViewSectionNode : TreeNode
    {
        const string CTX_MENU_ADD_SUB = "Add sub-section";
        const string CTX_MENU_ADD_PARAM_PAGE = "Add param page";
        const string CTX_MENU_DELETE = "Delete param section and all sub-sections/param pages";
        const string CTX_MENU_RENAME = "Rename section";
        /// <summary>
        /// Public constructor
        /// </summary>
        /// <param name="iName">Display name</param>
        /// <param name="iPath">File path for the UC definition file</param>
        /// <param name="iRefPage">Array of all of the associated UC tab page references</param>
        /// <param name="irefUC">Associated "User Control"</param>
        /// <param name="iPar">Parent OMX Param form</param>
        public OMXParamTreeViewSectionNode(string iName, string[] iPath, int[] iRefPage, UCTabPage irefUC, IOMXTreeViewParentForm iPar)
            : base(iName)
        {
            ParentForm = iPar;

            ContextMenuStrip = new ContextMenuStrip();
            EventHandler eh = new EventHandler(ContextMenuHandler);
            ContextMenuStrip.Items.Add(CTX_MENU_ADD_PARAM_PAGE, null, eh);
            ContextMenuStrip.Items.Add(CTX_MENU_ADD_SUB, null, eh);
            ContextMenuStrip.Items.Add(CTX_MENU_DELETE, null, eh);
            ContextMenuStrip.Items.Add(CTX_MENU_RENAME, null, eh);

            OMXParamSectionName = iName;
            refUCTabPageControl = irefUC;
            if (iPath != null)
            {
                for (int i = 0; i < iPath.Length; i++)
                {
                    Nodes.Add(new OMXParamTreeViewTabPageRefNode(iPath[i], iRefPage[i], irefUC, ParentForm));
                }
            }
        }
        /// <summary>
        /// Display name
        /// </summary>
        public string OMXParamSectionName;
        UCTabPage refUCTabPageControl;
        IOMXTreeViewParentForm ParentForm;
        /// <summary>
        /// The OMX Component version number
        /// </summary>
        public const int OMXCompSectNodeVerMin = 0x0;
        /// <summary>
        /// The OMX Component version number
        /// </summary>
        public const int OMXCompSectNodeVerMax = 0x0;
        /// <summary>
        /// Internal OMX component root version
        /// </summary>
        public int OMXCompSectNodeVer = 0x0;
        /// <summary>
        /// Overrided ToString method
        /// </summary>
        /// <returns></returns>
        public override string ToString()
        {
            return OMXParamSectionName;
        }
        /// <summary>
        /// Selects the first UC Tab page from the reference array
        /// </summary>
        public void SelectFirstOMXParamTabPageNode()
        {
            for (int i = 0; i < Nodes.Count; i++)
            {
                if (Nodes[i].GetType() == typeof(OMXParamTreeViewTabPageRefNode))
                {
                    refUCTabPageControl.SelectOMXPage(((OMXParamTreeViewTabPageRefNode)Nodes[i]).OMXParamTabPageRefIndx);
                    break;
                }
            }
        }
        /// <summary>
        /// Selects a UC Tab page with the specified name
        /// </summary>
        /// <param name="iName">Name of the Tab Page</param>
        public void SelectOMXParamTabPageNode(string iName)
        {
            int i = 0;
            while (i < Nodes.Count &&
                    Nodes[i].GetType() == typeof(OMXParamTreeViewTabPageRefNode) &&
                    ((OMXParamTreeViewTabPageRefNode)Nodes[i]).OMXParamTabPageName != iName)
            {
                i++;
            }
            if (i < Nodes.Count)
            {
                refUCTabPageControl.SelectOMXPage(((OMXParamTreeViewTabPageRefNode)Nodes[i]).OMXParamTabPageRefIndx);
            }
        }

        private void ContextMenuHandler(object sender, EventArgs ea)
        {
            ToolStripItem tmpItem = (ToolStripItem)sender;
            ea.GetType();

            if (tmpItem.Text == CTX_MENU_ADD_PARAM_PAGE)
            {
                AuxQueryBox subCrtForm = new AuxQueryBox(AuxQueryBox.IfModeSel.Section_create);
                subCrtForm.Text = "Parameter tab page name";
                subCrtForm.tbQueryInputText.Text = "OMX Param Page";
                subCrtForm.lblQueryDescription.Text = "Parameter page name:";
                if (subCrtForm.ShowDialog() == DialogResult.OK)
                {
                    OMXParamTreeViewTabPageRefNode tmpNode = new OMXParamTreeViewTabPageRefNode(subCrtForm.GetInputText(), refUCTabPageControl.AddOMXParamPage(subCrtForm.GetInputText()), refUCTabPageControl, ParentForm);
                    Nodes.Add(tmpNode);
                    TreeView.SelectedNode = tmpNode;
                    ParentForm.OMXParamTreeViewNodeSelected(tmpNode);
                }
            }
            else if (tmpItem.Text == CTX_MENU_ADD_SUB)
            {
                AuxQueryBox subCrtForm = new AuxQueryBox(AuxQueryBox.IfModeSel.Section_create);
                if (subCrtForm.ShowDialog() == DialogResult.OK)
                {
                    TreeNode tmpNode = new OMXParamTreeViewSectionNode(subCrtForm.GetInputText(), null, null, refUCTabPageControl, ParentForm);
                    Nodes.Add(tmpNode);
                    TreeView.SelectedNode = tmpNode;
                    ParentForm.OMXParamTreeViewNodeSelected(tmpNode);
                }
            }
            else if (tmpItem.Text == CTX_MENU_DELETE)
            {
                TreeNode tmpNodeRef = Parent;
                TreeView.SelectedNode = Parent;
                DeleteOMXParamTabPageChildNodes();
                Parent.Nodes.Remove(this);
                ParentForm.OMXParamTreeViewNodeSelected(tmpNodeRef);
            }
            else if (tmpItem.Text == CTX_MENU_RENAME)
            {
                AuxQueryBox subCrtForm = new AuxQueryBox(AuxQueryBox.IfModeSel.Section_create, Text);
                if (subCrtForm.ShowDialog() == DialogResult.OK)
                {
                    OMXParamSectionName = subCrtForm.GetInputText();
                    Text = subCrtForm.GetInputText();
                }
            }
        }
        /// <summary>
        /// Updates the reference tab page index of an underlying OMX structure node
        /// </summary>
        /// <param name="idx">Reference index</param>
        public void UpdateOMXParamTabPageRefIndx(int idx)
        {
            for (int i = 0; i < Nodes.Count; i++)
            {
                if (Nodes[i].GetType() == typeof(OMXParamTreeViewSectionNode))
                    ((OMXParamTreeViewSectionNode)Nodes[i]).UpdateOMXParamTabPageRefIndx(idx);
                else if (Nodes[i].GetType() == typeof(OMXParamTreeViewTabPageRefNode))
                    ((OMXParamTreeViewTabPageRefNode)Nodes[i]).UpdateOMXParamTabPageRefIndx(idx);
            }
        }
        /// <summary>
        /// Sets the component instance handle to all present nodes
        /// </summary>
        /// <param name="id">OMX component instance handle</param>
        public void UpdateOMXCompInstanceId(uint id)
        {
            for (int i = 0; i < Nodes.Count; i++)
            {
                if (Nodes[i].GetType() == typeof(OMXParamTreeViewSectionNode))
                    ((OMXParamTreeViewSectionNode)Nodes[i]).UpdateOMXCompInstanceId(id);
                else if (Nodes[i].GetType() == typeof(OMXParamTreeViewTabPageRefNode))
                    ((OMXParamTreeViewTabPageRefNode)Nodes[i]).UpdateOMXCompInstanceId(id);
            }
        }
        /// <summary>
        /// Deletes all child nodes
        /// </summary>
        public void DeleteOMXParamTabPageChildNodes()
        {
            for (int i = 0; i < Nodes.Count; i++)
            {
                if (Nodes[i].GetType() == typeof(OMXParamTreeViewSectionNode))
                {
                    ((OMXParamTreeViewSectionNode)Nodes[i]).DeleteOMXParamTabPageChildNodes();
                }
                else if (Nodes[i].GetType() == typeof(OMXParamTreeViewTabPageRefNode))
                {
                    ((OMXParamTreeViewTabPageRefNode)Nodes[i]).DeleteOMXParamTabPage();
                    i -= 1;
                }
            }
        }
        /// <summary>
        /// Returns an array of all the underlying OMX Param page reference indeces
        /// </summary>
        /// <returns>Index array</returns>
        public int[] GetOMXParamTabPageRefIndces()
        {
            List<int> indeces = new List<int>();
            for (int i = 0; i < Nodes.Count; i++)
            {
                if (Nodes[i].GetType() == typeof(OMXParamTreeViewSectionNode))
                    indeces.AddRange(((OMXParamTreeViewSectionNode)Nodes[i]).GetOMXParamTabPageRefIndces());
                else if (Nodes[i].GetType() == typeof(OMXParamTreeViewTabPageRefNode))
                    indeces.Add(((OMXParamTreeViewTabPageRefNode)Nodes[i]).OMXParamTabPageRefIndx);
            }
            return indeces.ToArray();
        }
    }
    #endregion
    #region OMX Param tree view tab page reference node
    /// <summary>
    /// An OMX component - config/param structure node
    /// </summary>
    public class OMXParamTreeViewTabPageRefNode : TreeNode
    {
        const string CTX_MENU_DELETE = "Delete param page";
        const string CTX_MENU_RENAME = "Rename param page";
        const string CTX_MENU_PAGE_PROPS = "Open param page properties";
        /// <summary>
        /// Public constructor
        /// </summary>
        /// <param name="ifInf">File for serialization</param>
        /// <param name="refPage">UI Tab page index</param>
        /// <param name="irefUC">Associated "User Control"</param>
        /// <param name="iPar">Parent OMX param form</param>
        public OMXParamTreeViewTabPageRefNode(string ifInf, int refPage, UCTabPage irefUC, IOMXTreeViewParentForm iPar)
            : base(ifInf)
        {
            ParentForm = iPar;

            ContextMenuStrip = new ContextMenuStrip();
            EventHandler eh = new EventHandler(ContextMenuHandler);
            ContextMenuStrip.Items.Add(CTX_MENU_DELETE, null, eh);
            ContextMenuStrip.Items.Add(CTX_MENU_RENAME, null, eh);
            ContextMenuStrip.Items.Add(CTX_MENU_PAGE_PROPS, null, eh);

            OMXParamTabPageName = ifInf;
            refUCTabPageControl = irefUC;
            OMXParamTabPageRefIndx = refPage;
        }

        UCTabPage refUCTabPageControl;
        /// <summary>
        /// Display name
        /// </summary>
        public string OMXParamTabPageName;
        /// <summary>
        /// Tab page reference index
        /// </summary>
        public int OMXParamTabPageRefIndx;
        IOMXTreeViewParentForm ParentForm;
        /// <summary>
        /// The OMX Component version number
        /// </summary>
        public const int OMXCompParamNodeVerMin = 0x0;
        /// <summary>
        /// The OMX Component version number
        /// </summary>
        public const int OMXCompParamNodeVerMax = 0x0;
        /// <summary>
        /// Internal OMX component node version
        /// </summary>
        public int OMXCompParamNodeVer = 0x0;

        private void ContextMenuHandler(object sender, EventArgs ea)
        {
            ToolStripItem tmpItem = (ToolStripItem)sender;
            ea.GetType();

            if (tmpItem.Text == CTX_MENU_DELETE)
            {
                DeleteOMXParamTabPage();
            }
            else if (tmpItem.Text == CTX_MENU_RENAME)
            {
                AuxQueryBox subCrtForm = new AuxQueryBox(AuxQueryBox.IfModeSel.Section_create, Text);
                if (subCrtForm.ShowDialog() == DialogResult.OK)
                {
                    OMXParamTabPageName = subCrtForm.GetInputText();
                    Text = subCrtForm.GetInputText();
                    refUCTabPageControl.RenameOMXParamPageProps(OMXParamTabPageRefIndx, subCrtForm.GetInputText());
                }
            }
            else if (tmpItem.Text == CTX_MENU_PAGE_PROPS)
            {
                refUCTabPageControl.GetOMXParamPageProps(OMXParamTabPageRefIndx);
            }
        }
        /// <summary>
        /// Selects the reference UC interface tab page
        /// </summary>
        public void SelectOMXParamTabPage()
        {
            refUCTabPageControl.SelectOMXPage(OMXParamTabPageRefIndx);
        }
        /// <summary>
        /// Sets the reference tab page index
        /// </summary>
        /// <param name="idx">Tab page index</param>
        public void UpdateOMXParamTabPageRefIndx(int idx)
        {
            if (idx < OMXParamTabPageRefIndx)
                OMXParamTabPageRefIndx -= 1;
        }
        /// <summary>
        /// Sets the OMX component instance handle
        /// </summary>
        /// <param name="id">OMX component instance handle</param>
        public void UpdateOMXCompInstanceId(uint id)
        {
            refUCTabPageControl.UpdateOMXCompInstanceId(OMXParamTabPageRefIndx, id);
        }
        /// <summary>
        /// Removes this node and its reference UC tab page
        /// </summary>
        public void DeleteOMXParamTabPage()
        {
            TreeNode tmpNodeRef = Parent;
            TreeView.SelectedNode = Parent;
            refUCTabPageControl.RemOMXParamPage(OMXParamTabPageRefIndx);

            TreeNode tmpNode = this;
            while (tmpNode.Parent != null)
                tmpNode = tmpNode.Parent;

            if (tmpNode.GetType() == typeof(OMXParamTreeViewRootNode))
                ((OMXParamTreeViewRootNode)tmpNode).UpdateOMXParamTabPageRefIndx(OMXParamTabPageRefIndx);

            ((OMXParamTreeViewSectionNode)Parent).Nodes.Remove(this);
            ParentForm.OMXParamTreeViewNodeSelected(tmpNodeRef);
        }
    }
    #endregion
}
